package com.ljc.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ljc.entity.Post;
import com.ljc.entity.User;
import com.ljc.mapper.PostMapper;
import com.ljc.mapper.UserMapper;
import com.ljc.service.PostService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ljc.utils.RedisUtil;
import com.ljc.vo.PostVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author feiyu
 * @since 2021-11-20
 */
@Service
public class PostServiceImpl extends ServiceImpl<PostMapper, Post> implements PostService {
    @Autowired
    PostMapper postMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    RedisUtil redisUtil;

    @Override
    public IPage<PostVo> paging(Page page, Long categoryId, Long userId, Integer level, Boolean recommend, String order) {
        if (level == null) {
            level = -1;
        }
        QueryWrapper wrapper = new QueryWrapper<Post>()
                .eq(categoryId != null, "category_id", categoryId)
                .eq(userId != null, "user_Id", userId)
                .eq(level == 0, "level", 0)
                .eq(level > 0, "level", 1)
                .orderByDesc(order != null, order);
        IPage<PostVo> postVoIPage = postMapper.selectPosts(page, wrapper);
        return postVoIPage;
    }

    @Override
    public PostVo selectOnePost(QueryWrapper<Post> wrapper) {
        return postMapper.selectOnePost(wrapper);
    }

    /**
     * 本周热议初始化
     *
     * @Author: ljc
     * @Date:Created in 21:04 2021/12/7
     */
    @Override
    public void initWeekRank() {
        //获取7天的发表文章
        List<Post> posts = this.list(new QueryWrapper<Post>()
                .ge("created", DateUtil.offsetDay(new Date(), -7))
                .select("id,title,user_id,comment_count,view_count,created"));
        //初始化文章总评论数
        for (Post post : posts) {
            String key = "day:rank:" + DateUtil.format(post.getCreated(), DatePattern.PURE_DATE_FORMAT);
            //key存入redis中 時間， 評論id  評論數
            redisUtil.zSet(key, post.getId(), post.getCommentCount());
            //设置七天自动过期（现在的时间减去创建时间）
            long between = DateUtil.between(new Date(), post.getCreated(), DateUnit.DAY);
            long expireTime = (7 - between) * 24 * 60 * 60;//有效时间
            redisUtil.expire(key, expireTime);
            //缓存文章一些基础信息（id，标题，评论数，作者）
            this.hashCachePostIdAndTitle(post, expireTime);
        }

        //做并集
        this.zunionAndStoreLast7DayWeekRank();

    }

    /**
     * 文章每日评论并集
     *
     * @Author: ljc
     * @Date:Created in 21:42 2021/12/7
     */
    private void zunionAndStoreLast7DayWeekRank() {
        String currentKey = "day:rank:" + DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT);
        String destKey = "week:rank";
        List<String> otherKeys = new ArrayList<>();
        //求前六天的合集
        for (int i = -6; i < 0; i++) {
            String temp = "day:rank:"
                    + DateUtil.format(DateUtil.offsetDay(new Date(), i), DatePattern.PURE_DATE_FORMAT);
            otherKeys.add(temp);
        }
        redisUtil.zUnionAndStore(currentKey, otherKeys, destKey);
    }

    /**
     * 缓存文章基本信息
     *
     * @Author: ljc
     * @Date:Created in 21:37 2021/12/7
     */
    private void hashCachePostIdAndTitle(Post post, long expireTime) {
        String key = "rank:post:" + post.getId();
        boolean hasKey = redisUtil.hasKey(key);
        if (!hasKey) {
            redisUtil.hset(key, "post:id", post.getId(), expireTime);
            redisUtil.hset(key, "post:title", post.getTitle(), expireTime);
            redisUtil.hset(key, "post:commentCount", post.getCommentCount(), expireTime);
            redisUtil.hset(key,"post:viewCount",post.getViewCount(),expireTime);
        }
    }

    /**
     * 添加评论
     *
     * @Author: ljc
     * @Date:Created in 20:13 2021/12/8
     */
    @Override
    public void incrCommentCountAndUnionForWeekRank(Long postId, boolean isIncr) {
        String currentKey = "day:rank:" + DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT);
        redisUtil.zIncrementScore(currentKey, postId, isIncr ? 1 : -1);
        Post post = this.getById(postId);

        //设置七天自动过期（现在的时间减去创建时间）
        long between = DateUtil.between(new Date(), post.getCreated(), DateUnit.DAY);
        long expireTime = (7 - between) * 24 * 60 * 60;//有效时间
        //缓存这篇文章的基本信息
        this.hashCachePostIdAndTitle(post, expireTime);
        //重新做并集
        this.zunionAndStoreLast7DayWeekRank();
    }

    //浏览量增加实现
    @Override
    public void putViewCount(PostVo vo) {
        String key = "rank:post:" + vo.getId();
        //1.从缓存获取viewCount
        Integer viewCount = (Integer) redisUtil.hget(key,"post:viewCount");
        // 2.如果没有就先从实体里面获取在加1
        if (viewCount!=null){
            vo.setViewCount(viewCount+1);
        }
        else {
            vo.setViewCount(vo.getViewCount()+1);
        }
        //3.同步到缓存里面
        redisUtil.hset(key, "post:viewCount",vo.getViewCount());
    }
}
